package org.jivesoftware.smack.util.collections;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;

public class AbstractHashedMap<K, V> extends AbstractMap<K, V>
  implements IterableMap<K, V>
{
  protected static final int DEFAULT_CAPACITY = 16;
  protected static final float DEFAULT_LOAD_FACTOR = 0.75F;
  protected static final int DEFAULT_THRESHOLD = 12;
  protected static final String GETKEY_INVALID = "getKey() can only be called after next() and before remove()";
  protected static final String GETVALUE_INVALID = "getValue() can only be called after next() and before remove()";
  protected static final int MAXIMUM_CAPACITY = 1073741824;
  protected static final String NO_NEXT_ENTRY = "No next() entry in the iteration";
  protected static final String NO_PREVIOUS_ENTRY = "No previous() entry in the iteration";
  protected static final Object NULL = new Object();
  protected static final String REMOVE_INVALID = "remove() can only be called once after next()";
  protected static final String SETVALUE_INVALID = "setValue() can only be called after next() and before remove()";
  protected transient HashEntry<K, V>[] data;
  protected transient EntrySet<K, V> entrySet;
  protected transient KeySet<K, V> keySet;
  protected transient float loadFactor;
  protected transient int modCount;
  protected transient int size;
  protected transient int threshold;
  protected transient Values<K, V> values;

  protected AbstractHashedMap(int paramInt)
  {
    this(paramInt, 0.75F);
  }

  protected AbstractHashedMap(int paramInt, float paramFloat)
  {
    if (paramInt < 1)
      throw new IllegalArgumentException("Initial capacity must be greater than 0");
    if ((paramFloat <= 0F) || (Float.isNaN(paramFloat)))
      throw new IllegalArgumentException("Load factor must be greater than 0");
    this.loadFactor = paramFloat;
    this.threshold = calculateThreshold(paramInt, paramFloat);
    this.data = new HashEntry[calculateNewCapacity(paramInt)];
    init();
  }

  protected AbstractHashedMap(int paramInt1, float paramFloat, int paramInt2)
  {
    this.loadFactor = paramFloat;
    this.data = new HashEntry[paramInt1];
    this.threshold = paramInt2;
    init();
  }

  protected AbstractHashedMap(Map<? extends K, ? extends V> paramMap)
  {
    this(Math.max(2 * paramMap.size(), 16), 0.75F);
    putAll(paramMap);
  }

  protected void addEntry(HashEntry<K, V> paramHashEntry, int paramInt)
  {
    this.data[paramInt] = paramHashEntry;
  }

  protected void addMapping(int paramInt1, int paramInt2, K paramK, V paramV)
  {
    this.modCount = (1 + this.modCount);
    addEntry(createEntry(this.data[paramInt1], paramInt2, paramK, paramV), paramInt1);
    this.size = (1 + this.size);
    checkCapacity();
  }

  protected int calculateNewCapacity(int paramInt)
  {
    int i = 1;
    if (paramInt > 1073741824)
      i = 1073741824;
    while (true)
    {
      do
      {
        return i;
        do
          i <<= 1;
        while (i < paramInt);
      }
      while (i <= 1073741824);
      i = 1073741824;
    }
  }

  protected int calculateThreshold(int paramInt, float paramFloat)
  {
    return (int)(paramFloat * paramInt);
  }

  protected void checkCapacity()
  {
    if (this.size >= this.threshold)
    {
      int i = 2 * this.data.length;
      if (i <= 1073741824)
        ensureCapacity(i);
    }
  }

  public void clear()
  {
    this.modCount = (1 + this.modCount);
    HashEntry[] arrayOfHashEntry = this.data;
    int i = arrayOfHashEntry.length - 1;
    while (true)
    {
      if (i < 0)
      {
        this.size = 0;
        return;
      }
      arrayOfHashEntry[i] = null;
      --i;
    }
  }

  protected Object clone()
  {
    AbstractHashedMap localAbstractHashedMap1;
    AbstractHashedMap localAbstractHashedMap2;
    try
    {
      localAbstractHashedMap2 = (AbstractHashedMap)super.clone();
      localAbstractHashedMap2.data = new HashEntry[this.data.length];
      localAbstractHashedMap2.entrySet = null;
      localAbstractHashedMap2.keySet = null;
      localAbstractHashedMap2.values = null;
      localAbstractHashedMap2.modCount = 0;
      localAbstractHashedMap2.size = 0;
      localAbstractHashedMap2.init();
      localAbstractHashedMap2.putAll(this);
      localAbstractHashedMap1 = localAbstractHashedMap2;
      return localAbstractHashedMap1;
    }
    catch (CloneNotSupportedException localCloneNotSupportedException)
    {
      localAbstractHashedMap1 = null;
    }
  }

  public boolean containsKey(Object paramObject)
  {
    Object localObject;
    int i;
    HashEntry localHashEntry;
    if (paramObject == null)
    {
      localObject = NULL;
      i = hash(localObject);
      localHashEntry = this.data[hashIndex(i, this.data.length)];
    }
    while (true)
    {
      int j;
      if (localHashEntry == null)
        j = 0;
      while (true)
      {
        while (true)
        {
          return j;
          localObject = paramObject;
        }
        if ((localHashEntry.hashCode != i) || (!(isEqualKey(paramObject, localHashEntry.getKey()))))
          break;
        j = 1;
      }
      localHashEntry = localHashEntry.next;
    }
  }

  public boolean containsValue(Object paramObject)
  {
    int i;
    int j;
    int k;
    int l;
    if (paramObject == null)
    {
      l = 0;
      int i1 = this.data.length;
      if (l >= i1);
    }
    do
    {
      k = 0;
      return k;
      HashEntry localHashEntry2 = this.data[l];
      while (true)
      {
        while (true)
        {
          while (localHashEntry2 == null)
            ++l;
          if (localHashEntry2.getValue() != null)
            break;
          k = 1;
        }
        localHashEntry2 = localHashEntry2.next;
      }
      i = 0;
      j = this.data.length;
    }
    while (i >= j);
    HashEntry localHashEntry1 = this.data[i];
    while (true)
    {
      while (true)
      {
        while (localHashEntry1 == null)
          ++i;
        if (!(isEqualValue(paramObject, localHashEntry1.getValue())))
          break;
        k = 1;
      }
      localHashEntry1 = localHashEntry1.next;
    }
  }

  protected HashEntry<K, V> createEntry(HashEntry<K, V> paramHashEntry, int paramInt, K paramK, V paramV)
  {
    return new HashEntry(paramHashEntry, paramInt, paramK, paramV);
  }

  protected Iterator<Map.Entry<K, V>> createEntrySetIterator()
  {
    Object localObject;
    if (size() == 0)
      localObject = EmptyIterator.INSTANCE;
    while (true)
    {
      return localObject;
      localObject = new EntrySetIterator(this);
    }
  }

  protected Iterator<K> createKeySetIterator()
  {
    Object localObject;
    if (size() == 0)
      localObject = EmptyIterator.INSTANCE;
    while (true)
    {
      return localObject;
      localObject = new KeySetIterator(this);
    }
  }

  protected Iterator<V> createValuesIterator()
  {
    Object localObject;
    if (size() == 0)
      localObject = EmptyIterator.INSTANCE;
    while (true)
    {
      return localObject;
      localObject = new ValuesIterator(this);
    }
  }

  protected void destroyEntry(HashEntry<K, V> paramHashEntry)
  {
    paramHashEntry.next = null;
    HashEntry.access$1(paramHashEntry, null);
    HashEntry.access$2(paramHashEntry, null);
  }

  protected void doReadObject(ObjectInputStream paramObjectInputStream)
    throws IOException, ClassNotFoundException
  {
    this.loadFactor = paramObjectInputStream.readFloat();
    int i = paramObjectInputStream.readInt();
    int j = paramObjectInputStream.readInt();
    init();
    this.data = new HashEntry[i];
    int k = 0;
    while (true)
    {
      if (k >= j)
      {
        this.threshold = calculateThreshold(this.data.length, this.loadFactor);
        return;
      }
      put(paramObjectInputStream.readObject(), paramObjectInputStream.readObject());
      ++k;
    }
  }

  protected void doWriteObject(ObjectOutputStream paramObjectOutputStream)
    throws IOException
  {
    paramObjectOutputStream.writeFloat(this.loadFactor);
    paramObjectOutputStream.writeInt(this.data.length);
    paramObjectOutputStream.writeInt(this.size);
    MapIterator localMapIterator = mapIterator();
    while (true)
    {
      if (!(localMapIterator.hasNext()))
        return;
      paramObjectOutputStream.writeObject(localMapIterator.next());
      paramObjectOutputStream.writeObject(localMapIterator.getValue());
    }
  }

  protected void ensureCapacity(int paramInt)
  {
    int i = this.data.length;
    if (paramInt <= i);
    while (true)
    {
      return;
      if (this.size != 0)
        break;
      this.threshold = calculateThreshold(paramInt, this.loadFactor);
      this.data = new HashEntry[paramInt];
    }
    HashEntry[] arrayOfHashEntry1 = this.data;
    HashEntry[] arrayOfHashEntry2 = new HashEntry[paramInt];
    this.modCount = (1 + this.modCount);
    int j = i - 1;
    while (true)
    {
      while (j < 0)
      {
        this.threshold = calculateThreshold(paramInt, this.loadFactor);
        this.data = arrayOfHashEntry2;
      }
      Object localObject = arrayOfHashEntry1[j];
      if (localObject != null)
      {
        arrayOfHashEntry1[j] = null;
        do
        {
          HashEntry localHashEntry = ((HashEntry)localObject).next;
          int k = hashIndex(((HashEntry)localObject).hashCode, paramInt);
          ((HashEntry)localObject).next = arrayOfHashEntry2[k];
          arrayOfHashEntry2[k] = localObject;
          localObject = localHashEntry;
        }
        while (localObject != null);
      }
      --j;
    }
  }

  protected int entryHashCode(HashEntry<K, V> paramHashEntry)
  {
    return paramHashEntry.hashCode;
  }

  protected K entryKey(HashEntry<K, V> paramHashEntry)
  {
    return HashEntry.access$0(paramHashEntry);
  }

  protected HashEntry<K, V> entryNext(HashEntry<K, V> paramHashEntry)
  {
    return paramHashEntry.next;
  }

  public Set<Map.Entry<K, V>> entrySet()
  {
    if (this.entrySet == null)
      this.entrySet = new EntrySet(this);
    return this.entrySet;
  }

  protected V entryValue(HashEntry<K, V> paramHashEntry)
  {
    return HashEntry.access$3(paramHashEntry);
  }

  public boolean equals(Object paramObject)
  {
    Map localMap;
    int i;
    if (paramObject == this)
      i = 1;
    while (true)
    {
      while (true)
      {
        return i;
        if (paramObject instanceof Map)
          break;
        i = 0;
      }
      localMap = (Map)paramObject;
      if (localMap.size() == size())
        break;
      i = 0;
    }
    MapIterator localMapIterator = mapIterator();
    try
    {
      label114: boolean bool;
      do
      {
        Object localObject1;
        Object localObject2;
        do
        {
          while (!(localMapIterator.hasNext()))
            i = 1;
          localObject1 = localMapIterator.next();
          localObject2 = localMapIterator.getValue();
          if (localObject2 != null)
            break label114;
          if (localMap.get(localObject1) != null)
            break label156;
        }
        while (localMap.containsKey(localObject1));
        break label156:
        bool = localObject2.equals(localMap.get(localObject1));
      }
      while (bool);
      label156: i = 0;
    }
    catch (ClassCastException localClassCastException)
    {
      i = 0;
    }
    catch (NullPointerException localNullPointerException)
    {
      while (true)
        i = 0;
      i = 0;
    }
  }

  public V get(Object paramObject)
  {
    Object localObject1;
    int i;
    HashEntry localHashEntry;
    if (paramObject == null)
    {
      localObject1 = NULL;
      i = hash(localObject1);
      localHashEntry = this.data[hashIndex(i, this.data.length)];
    }
    while (true)
    {
      Object localObject2;
      if (localHashEntry == null)
        localObject2 = null;
      while (true)
      {
        while (true)
        {
          return localObject2;
          localObject1 = paramObject;
        }
        if ((localHashEntry.hashCode != i) || (!(isEqualKey(paramObject, HashEntry.access$0(localHashEntry)))))
          break;
        localObject2 = localHashEntry.getValue();
      }
      localHashEntry = localHashEntry.next;
    }
  }

  protected HashEntry<K, V> getEntry(Object paramObject)
  {
    Object localObject;
    int i;
    HashEntry localHashEntry1;
    if (paramObject == null)
    {
      localObject = NULL;
      i = hash(localObject);
      localHashEntry1 = this.data[hashIndex(i, this.data.length)];
    }
    while (true)
    {
      HashEntry localHashEntry2;
      if (localHashEntry1 == null)
        localHashEntry2 = null;
      while (true)
      {
        while (true)
        {
          return localHashEntry2;
          localObject = paramObject;
        }
        if ((localHashEntry1.hashCode != i) || (!(isEqualKey(paramObject, localHashEntry1.getKey()))))
          break;
        localHashEntry2 = localHashEntry1;
      }
      localHashEntry1 = localHashEntry1.next;
    }
  }

  protected int hash(Object paramObject)
  {
    int i = paramObject.hashCode();
    int j = i + (0xFFFFFFFF ^ i << 9);
    int k = j ^ j >>> 14;
    int l = k + (k << 4);
    return (l ^ l >>> 10);
  }

  public int hashCode()
  {
    int i = 0;
    Iterator localIterator = createEntrySetIterator();
    while (true)
    {
      if (!(localIterator.hasNext()))
        return i;
      i += localIterator.next().hashCode();
    }
  }

  protected int hashIndex(int paramInt1, int paramInt2)
  {
    return (paramInt1 & paramInt2 - 1);
  }

  protected void init()
  {
  }

  public boolean isEmpty()
  {
    int i;
    if (this.size == 0)
      i = 1;
    while (true)
    {
      return i;
      i = 0;
    }
  }

  protected boolean isEqualKey(Object paramObject1, Object paramObject2)
  {
    int i;
    if ((paramObject1 != paramObject2) && (((paramObject1 == null) || (!(paramObject1.equals(paramObject2))))))
      i = 0;
    while (true)
    {
      return i;
      i = 1;
    }
  }

  protected boolean isEqualValue(Object paramObject1, Object paramObject2)
  {
    int i;
    if ((paramObject1 != paramObject2) && (!(paramObject1.equals(paramObject2))))
      i = 0;
    while (true)
    {
      return i;
      i = 1;
    }
  }

  public Set<K> keySet()
  {
    if (this.keySet == null)
      this.keySet = new KeySet(this);
    return this.keySet;
  }

  public MapIterator<K, V> mapIterator()
  {
    Object localObject;
    if (this.size == 0)
      localObject = EmptyMapIterator.INSTANCE;
    while (true)
    {
      return localObject;
      localObject = new HashMapIterator(this);
    }
  }

  public V put(K paramK, V paramV)
  {
    Object localObject1;
    int i;
    int j;
    HashEntry localHashEntry;
    if (paramK == null)
    {
      localObject1 = NULL;
      i = hash(localObject1);
      j = hashIndex(i, this.data.length);
      localHashEntry = this.data[j];
    }
    while (true)
    {
      Object localObject3;
      if (localHashEntry == null)
      {
        addMapping(j, i, paramK, paramV);
        localObject3 = null;
      }
      while (true)
      {
        while (true)
        {
          return localObject3;
          localObject1 = paramK;
        }
        if ((localHashEntry.hashCode != i) || (!(isEqualKey(paramK, localHashEntry.getKey()))))
          break;
        Object localObject2 = localHashEntry.getValue();
        updateEntry(localHashEntry, paramV);
        localObject3 = localObject2;
      }
      localHashEntry = localHashEntry.next;
    }
  }

  public void putAll(Map<? extends K, ? extends V> paramMap)
  {
    int i = paramMap.size();
    if (i == 0)
      return;
    ensureCapacity(calculateNewCapacity((int)(1F + (i + this.size) / this.loadFactor)));
    Iterator localIterator = paramMap.entrySet().iterator();
    while (true)
    {
      if (!(localIterator.hasNext()));
      Map.Entry localEntry = (Map.Entry)localIterator.next();
      put(localEntry.getKey(), localEntry.getValue());
    }
  }

  public V remove(Object paramObject)
  {
    Object localObject1;
    int i;
    int j;
    HashEntry localHashEntry1;
    HashEntry localHashEntry2;
    if (paramObject == null)
    {
      localObject1 = NULL;
      i = hash(localObject1);
      j = hashIndex(i, this.data.length);
      localHashEntry1 = this.data[j];
      localHashEntry2 = null;
    }
    while (true)
    {
      Object localObject3;
      if (localHashEntry1 == null)
        localObject3 = null;
      while (true)
      {
        while (true)
        {
          return localObject3;
          localObject1 = paramObject;
        }
        if ((localHashEntry1.hashCode != i) || (!(isEqualKey(paramObject, localHashEntry1.getKey()))))
          break;
        Object localObject2 = localHashEntry1.getValue();
        removeMapping(localHashEntry1, j, localHashEntry2);
        localObject3 = localObject2;
      }
      localHashEntry2 = localHashEntry1;
      localHashEntry1 = localHashEntry1.next;
    }
  }

  protected void removeEntry(HashEntry<K, V> paramHashEntry1, int paramInt, HashEntry<K, V> paramHashEntry2)
  {
    if (paramHashEntry2 == null)
      this.data[paramInt] = paramHashEntry1.next;
    while (true)
    {
      return;
      paramHashEntry2.next = paramHashEntry1.next;
    }
  }

  protected void removeMapping(HashEntry<K, V> paramHashEntry1, int paramInt, HashEntry<K, V> paramHashEntry2)
  {
    this.modCount = (1 + this.modCount);
    removeEntry(paramHashEntry1, paramInt, paramHashEntry2);
    this.size -= 1;
    destroyEntry(paramHashEntry1);
  }

  protected void reuseEntry(HashEntry<K, V> paramHashEntry, int paramInt1, int paramInt2, K paramK, V paramV)
  {
    paramHashEntry.next = this.data[paramInt1];
    paramHashEntry.hashCode = paramInt2;
    HashEntry.access$1(paramHashEntry, paramK);
    HashEntry.access$2(paramHashEntry, paramV);
  }

  public int size()
  {
    return this.size;
  }

  public String toString()
  {
    StringBuilder localStringBuilder1;
    MapIterator localMapIterator;
    boolean bool;
    Object localObject3;
    StringBuilder localStringBuilder2;
    Object localObject4;
    String str;
    if (size() == 0)
      str = "{}";
    while (true)
    {
      return str;
      localStringBuilder1 = new StringBuilder(32 * size());
      localStringBuilder1.append('{');
      localMapIterator = mapIterator();
      bool = localMapIterator.hasNext();
      if (bool)
        break;
      localStringBuilder1.append('}');
      str = localStringBuilder1.toString();
    }
    Object localObject1 = localMapIterator.next();
    Object localObject2 = localMapIterator.getValue();
    if (localObject1 == this)
    {
      localObject3 = "(this Map)";
      localStringBuilder2 = localStringBuilder1.append(localObject3).append('=');
      if (localObject2 != this)
        break label165;
      localObject4 = "(this Map)";
    }
    while (true)
    {
      while (true)
      {
        while (true)
        {
          do
          {
            localStringBuilder2.append(localObject4);
            bool = localMapIterator.hasNext();
          }
          while (!(bool));
          localStringBuilder1.append(',').append(' ');
        }
        localObject3 = localObject1;
      }
      label165: localObject4 = localObject2;
    }
  }

  protected void updateEntry(HashEntry<K, V> paramHashEntry, V paramV)
  {
    paramHashEntry.setValue(paramV);
  }

  public Collection<V> values()
  {
    if (this.values == null)
      this.values = new Values(this);
    return this.values;
  }

  protected static class EntrySet<K, V> extends AbstractSet<Map.Entry<K, V>>
  {
    protected final AbstractHashedMap<K, V> parent;

    protected EntrySet(AbstractHashedMap<K, V> paramAbstractHashedMap)
    {
      this.parent = paramAbstractHashedMap;
    }

    public void clear()
    {
      this.parent.clear();
    }

    public boolean contains(Map.Entry<K, V> paramEntry)
    {
      int i;
      AbstractHashedMap.HashEntry localHashEntry = this.parent.getEntry(paramEntry.getKey());
      if ((localHashEntry != null) && (localHashEntry.equals(paramEntry)))
        i = 1;
      while (true)
      {
        return i;
        i = 0;
      }
    }

    public Iterator<Map.Entry<K, V>> iterator()
    {
      return this.parent.createEntrySetIterator();
    }

    public boolean remove(Object paramObject)
    {
      int i;
      if (!(paramObject instanceof Map.Entry))
        i = 0;
      while (true)
      {
        while (true)
        {
          return i;
          if (contains(paramObject))
            break;
          i = 0;
        }
        Object localObject = ((Map.Entry)paramObject).getKey();
        this.parent.remove(localObject);
        i = 1;
      }
    }

    public int size()
    {
      return this.parent.size();
    }
  }

  protected static class EntrySetIterator<K, V> extends AbstractHashedMap.HashIterator<K, V>
  implements Iterator<Map.Entry<K, V>>
  {
    protected EntrySetIterator(AbstractHashedMap<K, V> paramAbstractHashedMap)
    {
      super(paramAbstractHashedMap);
    }

    public AbstractHashedMap.HashEntry<K, V> next()
    {
      return super.nextEntry();
    }
  }

  protected static class HashEntry<K, V>
  implements Map.Entry<K, V>, KeyValue<K, V>
  {
    protected int hashCode;
    private K key;
    protected HashEntry<K, V> next;
    private V value;

    protected HashEntry(HashEntry<K, V> paramHashEntry, int paramInt, K paramK, V paramV)
    {
      this.next = paramHashEntry;
      this.hashCode = paramInt;
      this.key = paramK;
      this.value = paramV;
    }

    public boolean equals(Object paramObject)
    {
      int i;
      if (paramObject == this)
        i = 1;
      while (true)
      {
        return i;
        if (paramObject instanceof Map.Entry)
          break;
        i = 0;
      }
      Map.Entry localEntry = (Map.Entry)paramObject;
      if (getKey() == null)
      {
        if (localEntry.getKey() != null)
          break label79;
        if (getValue() != null)
          break label84;
        if (localEntry.getValue() != null)
          break label79;
      }
      while (true)
      {
        do
          while (true)
            i = 1;
        while (getKey().equals(localEntry.getKey()));
        label79: label84: 
        do
          while (true)
            i = 0;
        while (!(getValue().equals(localEntry.getValue())));
      }
    }

    public K getKey()
    {
      return this.key;
    }

    public V getValue()
    {
      return this.value;
    }

    public int hashCode()
    {
      int i;
      int j;
      if (getKey() == null)
      {
        i = 0;
        if (getValue() != null)
          break label33;
        j = 0;
      }
      while (true)
      {
        while (true)
        {
          return (i ^ j);
          i = getKey().hashCode();
        }
        label33: j = getValue().hashCode();
      }
    }

    public void setKey(K paramK)
    {
      this.key = paramK;
    }

    public V setValue(V paramV)
    {
      Object localObject = this.value;
      this.value = paramV;
      return localObject;
    }

    public String toString()
    {
      return getKey() + '=' + getValue();
    }
  }

  protected static abstract class HashIterator<K, V>
  {
    protected int expectedModCount;
    protected int hashIndex;
    protected AbstractHashedMap.HashEntry<K, V> last;
    protected AbstractHashedMap.HashEntry<K, V> next;
    protected final AbstractHashedMap parent;

    protected HashIterator(AbstractHashedMap<K, V> paramAbstractHashedMap)
    {
      this.parent = paramAbstractHashedMap;
      AbstractHashedMap.HashEntry[] arrayOfHashEntry = paramAbstractHashedMap.data;
      int i = arrayOfHashEntry.length;
      Object localObject = null;
      while (true)
      {
        if ((i <= 0) || (localObject != null))
        {
          this.next = localObject;
          this.hashIndex = i;
          this.expectedModCount = paramAbstractHashedMap.modCount;
          return;
        }
        localObject = ???[(--i)];
      }
    }

    protected AbstractHashedMap.HashEntry<K, V> currentEntry()
    {
      return this.last;
    }

    public boolean hasNext()
    {
      int i;
      if (this.next != null)
        i = 1;
      while (true)
      {
        return i;
        i = 0;
      }
    }

    protected AbstractHashedMap.HashEntry<K, V> nextEntry()
    {
      if (this.parent.modCount != this.expectedModCount)
        throw new ConcurrentModificationException();
      AbstractHashedMap.HashEntry localHashEntry1 = this.next;
      if (localHashEntry1 == null)
        throw new NoSuchElementException("No next() entry in the iteration");
      AbstractHashedMap.HashEntry[] arrayOfHashEntry = this.parent.data;
      int i = this.hashIndex;
      AbstractHashedMap.HashEntry localHashEntry2 = localHashEntry1.next;
      while (true)
      {
        if ((localHashEntry2 != null) || (i <= 0))
        {
          this.next = localHashEntry2;
          this.hashIndex = i;
          this.last = localHashEntry1;
          return localHashEntry1;
        }
        localHashEntry2 = ???[(--i)];
      }
    }

    public void remove()
    {
      if (this.last == null)
        throw new IllegalStateException("remove() can only be called once after next()");
      if (this.parent.modCount != this.expectedModCount)
        throw new ConcurrentModificationException();
      this.parent.remove(this.last.getKey());
      this.last = null;
      this.expectedModCount = this.parent.modCount;
    }

    public String toString()
    {
      String str;
      if (this.last != null)
        str = "Iterator[" + this.last.getKey() + "=" + this.last.getValue() + "]";
      while (true)
      {
        return str;
        str = "Iterator[]";
      }
    }
  }

  protected static class HashMapIterator<K, V> extends AbstractHashedMap.HashIterator<K, V>
  implements MapIterator<K, V>
  {
    protected HashMapIterator(AbstractHashedMap<K, V> paramAbstractHashedMap)
    {
      super(paramAbstractHashedMap);
    }

    public K getKey()
    {
      AbstractHashedMap.HashEntry localHashEntry = currentEntry();
      if (localHashEntry == null)
        throw new IllegalStateException("getKey() can only be called after next() and before remove()");
      return localHashEntry.getKey();
    }

    public V getValue()
    {
      AbstractHashedMap.HashEntry localHashEntry = currentEntry();
      if (localHashEntry == null)
        throw new IllegalStateException("getValue() can only be called after next() and before remove()");
      return localHashEntry.getValue();
    }

    public K next()
    {
      return super.nextEntry().getKey();
    }

    public V setValue(V paramV)
    {
      AbstractHashedMap.HashEntry localHashEntry = currentEntry();
      if (localHashEntry == null)
        throw new IllegalStateException("setValue() can only be called after next() and before remove()");
      return localHashEntry.setValue(paramV);
    }
  }

  protected static class KeySet<K, V> extends AbstractSet<K>
  {
    protected final AbstractHashedMap<K, V> parent;

    protected KeySet(AbstractHashedMap<K, V> paramAbstractHashedMap)
    {
      this.parent = paramAbstractHashedMap;
    }

    public void clear()
    {
      this.parent.clear();
    }

    public boolean contains(Object paramObject)
    {
      return this.parent.containsKey(paramObject);
    }

    public Iterator<K> iterator()
    {
      return this.parent.createKeySetIterator();
    }

    public boolean remove(Object paramObject)
    {
      boolean bool = this.parent.containsKey(paramObject);
      this.parent.remove(paramObject);
      return bool;
    }

    public int size()
    {
      return this.parent.size();
    }
  }

  protected static class KeySetIterator<K, V> extends AbstractHashedMap.HashIterator<K, V>
  implements Iterator<K>
  {
    protected KeySetIterator(AbstractHashedMap<K, V> paramAbstractHashedMap)
    {
      super(paramAbstractHashedMap);
    }

    public K next()
    {
      return super.nextEntry().getKey();
    }
  }

  protected static class Values<K, V> extends AbstractCollection<V>
  {
    protected final AbstractHashedMap<K, V> parent;

    protected Values(AbstractHashedMap<K, V> paramAbstractHashedMap)
    {
      this.parent = paramAbstractHashedMap;
    }

    public void clear()
    {
      this.parent.clear();
    }

    public boolean contains(Object paramObject)
    {
      return this.parent.containsValue(paramObject);
    }

    public Iterator<V> iterator()
    {
      return this.parent.createValuesIterator();
    }

    public int size()
    {
      return this.parent.size();
    }
  }

  protected static class ValuesIterator<K, V> extends AbstractHashedMap.HashIterator<K, V>
  implements Iterator<V>
  {
    protected ValuesIterator(AbstractHashedMap<K, V> paramAbstractHashedMap)
    {
      super(paramAbstractHashedMap);
    }

    public V next()
    {
      return super.nextEntry().getValue();
    }
  }
}